package com.lancoo.ccas53.service.mobileService;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lancoo.ccas53.entity.Course;
import com.lancoo.ccas53.entity.Student;
import com.lancoo.ccas53.entity.Teacher;
import com.lancoo.ccas53.entity.TeachingClassStudent;
import com.lancoo.ccas53.mapper.CourseMapper;
import com.lancoo.ccas53.mapper.ScheduleMapper;
import com.lancoo.ccas53.mapper.StudentMapper;
import com.lancoo.ccas53.mapper.TeachingClassStudentMapper;
import com.lancoo.ccas53.pojo.vo.*;
import com.lancoo.ccas53.service.StudentService;
import com.lancoo.ccas53.service.TeacherService;
import com.lancoo.ccas53.service.TeachingClassService;
import com.lancoo.ccas53.service.impl.StudentServiceImpl;
import com.lancoo.ccas53.util.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: mabolin
 * @Date: 2024-07-12-16:17
 * @Description:
 */
@Service
@Slf4j
public class MobileStudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements MobileStudentService {
    @Resource
    private RedisUtil redisUtil;
    @Autowired
    private StudentServiceImpl studentServiceimpl;
    @Resource
    private TeachingClassService teachingClassService;
    @Resource
    private StudentMapper studentMapper;
    @Resource
    private ScheduleMapper scheduleMapper;
    @Resource
    private TeacherService teacherService;
    @Resource
    private TeachingClassStudentMapper teachingClassStudentMapper;
    @Resource
    private CourseMapper courseMapper;
    @Autowired
    private StudentService studentService;

    @Override
    public StudentTeachingClass getCourseDetail(Integer taskId, Long studentId, Integer teachingClassType, Long teachingClassId) {
        List<Long> classIds = new ArrayList<>();
        classIds.add(teachingClassId);
        List<StudentTeachingClass> teachingDetail = getTeachingClassDetail(taskId, classIds);
        teachingDetail = teachingDetail.stream().filter(detail -> detail.getTeachingClassType().equals(teachingClassType)).collect(Collectors.toList());
        if (teachingDetail.size() == 0) {
            return null;
        }
        for (StudentTeachingClass teachingClass : teachingDetail) {
            if (teachingClass.getCourseOrSegment() == 1) {
                Course course = courseMapper.selectById(teachingClass.getCourseId());
                teachingClass.setComputerHour(course.getComputerHour());
                teachingClass.setExperimentalHour(course.getExperimentalHour());
                teachingClass.setLectureHour(course.getLectureHour());
                teachingClass.setOtherHour(course.getOtherHour());
                teachingClass.setDescription(course.getDescription() == null ? "" : course.getDescription());
            } else if (teachingClass.getCourseOrSegment() == 2) {
                Course segment = courseMapper.selectById(teachingClass.getCourseId());
                teachingClass.setDescription(segment.getDescription() == null ? "" : segment.getDescription());
            }
            String redisKey = studentServiceimpl.getCacheKeys(taskId, null, 3, null);
            if (redisUtil.hHasKey(redisKey, studentId + "-" + teachingClassId)) {
                TeachingClassStudent tcs = (TeachingClassStudent) redisUtil.hget(redisKey, studentId + "-" + teachingClassId);
                teachingClass.setFlag(tcs.getFlag());
                teachingClass.setStatus(tcs.getFlag() == 1 ? 1 : 0);
            } else {
                TeachingClassStudent teachingClassStudent = teachingClassStudentMapper.selectOne(new LambdaQueryWrapper<TeachingClassStudent>()
                        .eq(TeachingClassStudent::getStudentId, studentId)
                        .eq(TeachingClassStudent::getTeachingClassId, teachingClass.getTeachingClassId()));
                if (teachingClassStudent != null) {
                    redisUtil.hset(studentServiceimpl.getCacheKeys(taskId, null, 3, null), studentId + "-" + teachingClassId, teachingClassStudent);
                    teachingClass.setFlag(teachingClassStudent.getFlag());
                    teachingClass.setStatus(teachingClassStudent.getFlag() == 1 ? 1 : 0);
                } else {
                    teachingClass.setStatus(0);
                }
            }
        }

        return teachingDetail.get(0);
    }

    @Override
    public SelectedCourseStatistics getStudentSelectedCourseStatisticsByStudentId(Integer taskId, Long studentId, Integer teachingClassType) {
        //获取学生都有哪些教学班
        List<StudentTeachingClass> teachingClassList = studentService.getSelectedByStudentId(taskId, studentId, teachingClassType);
        teachingClassList = teachingClassList.stream().filter(a -> a.getTeachingClassType() != 0).collect(Collectors.toList());
        SelectedCourseStatistics result = new SelectedCourseStatistics();
        result.setCourseNum(teachingClassList.size());
        Double totalCredits = teachingClassList.stream()
                .mapToDouble(StudentTeachingClass::getCredit)
                .sum();
        result.setCreditNum(totalCredits);
        List<CourseTypeStatisticsDto> list = new ArrayList<>();
        Map<String, Map<Integer, List<StudentTeachingClass>>> typeCounts = teachingClassList.stream()
                .collect(Collectors.groupingBy(StudentTeachingClass::getCourseTypeId,
                        Collectors.groupingBy(StudentTeachingClass::getStudyNature)));
        for (Map.Entry<String, Map<Integer, List<StudentTeachingClass>>> entryCourseType : typeCounts.entrySet()) {
            String courseTypeId = entryCourseType.getKey();
            CourseTypeStatisticsDto dto = new CourseTypeStatisticsDto();
            for (Map.Entry<Integer, List<StudentTeachingClass>> entryStudyNature : entryCourseType.getValue().entrySet()) {
                int studyNature = entryStudyNature.getKey();
                if (studyNature == 1) {
                    dto.setCourseTypeId(courseTypeId);
                    StudentTeachingClass teachingClass = entryStudyNature.getValue().get(0);
                    dto.setCourseType(teachingClass.getCourseType());
                    dto.setMajorCourseNum(entryStudyNature.getValue().size());
                } else {
                    dto.setCourseTypeId(courseTypeId);
                    StudentTeachingClass teachingClass = entryStudyNature.getValue().get(0);
                    dto.setCourseType(teachingClass.getCourseType());
                    dto.setMajorCourseNum(entryStudyNature.getValue().size());
                }
            }
            list.add(dto);
        }
        result.setCourseTypeStatistics(list);
        return result;
    }

    public List<StudentTeachingClass> getTeachingClassDetail(Integer taskId, List<Long> teachingClassIds) {
        List<StudentTeachingClass> list = new ArrayList<>();
        if (CollUtil.isEmpty(teachingClassIds)) {
            return list;
        }
        redisUtil.hgets(studentServiceimpl.getCacheKeys(taskId, null, 6, null), teachingClassIds.stream().map(String::valueOf).collect(Collectors.toSet()))
                .forEach(a -> {
                    if (a != null) {
                        list.add((StudentTeachingClass) a);
                    }
                });
        for (StudentTeachingClass teachingClass : list) {
            teachingClass.setCourseOrSegment(teachingClassService.getById(teachingClass.getTeachingClassId()).getFlag());
        }
        //redis 不存在的数据则查询数据库并缓存
        teachingClassIds.removeAll(list.stream().map(StudentTeachingClass::getTeachingClassId).collect(Collectors.toList()));
        if (CollUtil.isNotEmpty(teachingClassIds)) {
            //课程
            List<StudentTeachingClass> courseTeachingClass = studentMapper.getNormalCourseTeachingClass(teachingClassIds, null);
            //环节
            List<StudentTeachingClass> segmentTeachingClass = studentMapper.getNormalSegmentTeachingClass(teachingClassIds);
            courseTeachingClass.addAll(segmentTeachingClass);
            //填充教师信息
            Map<Long, List<Teacher>> teacherMap = teacherService.getTeacherByTeachingClassIdsArrange(teachingClassIds).stream()
                    .collect(Collectors.groupingBy(Teacher::getTeachingClassId));
            //课表信息
            List<MobileScheduleDto> scheduleDtoList = scheduleMapper.getScheduleByTeachingClassIds(null, teachingClassIds);
            Map<Long, List<MobileScheduleDto>> scheduleMap = scheduleDtoList.stream().collect(Collectors.groupingBy(MobileScheduleDto::getTeachingClassId));
            //学生人数
            Map<Long, Integer> studentNumMap = teachingClassStudentMapper.getStudentNumber(teachingClassIds)
                    .stream().collect(Collectors.toMap(TeachingClassCourseDto::getTeachingClassId, TeachingClassCourseDto::getStudentNumber));
            courseTeachingClass.forEach(a -> {
                a.setTeachers(teacherMap.get(a.getTeachingClassId()));
                a.setSchedules(scheduleMap.get(a.getTeachingClassId()));
                //学生人数
                a.setStudentNumber(studentNumMap.getOrDefault(a.getTeachingClassId(), 0));
            });
            list.addAll(courseTeachingClass);
            //缓存数据
            if (CollUtil.isNotEmpty(courseTeachingClass)) {
                redisUtil.hmset(studentServiceimpl.getCacheKeys(taskId, null, 6, null), courseTeachingClass.stream().collect(Collectors.toMap(a -> a.getTeachingClassId(), a -> a)), 60 * 60 * 24 * 7);
            }
        }
        return list;
    }
}
